<!doctype html>

<html lang="en">

<head>
  <meta charset="utf-8">
  <title>bars</title>
  <style>
    /* body{
      background-color: brown;
    } */

    .axis {
      font: 10px sans-serif;
    }

    .axis path,
    .axis line {
      fill: none;
      stroke: #000;
      shape-rendering: crispEdges;
    }

    .axis--y path {
      display: none;
    }

    .bar {
      fill: #3182bd;
      fill-opacity: .9;
    }

    .wld {
      fill: #9ecae1;
    }

    .chart-title {
      margin-bottom: 0;
    }

    .source {
      margin-top: 0;
      font-size: 11px;
    }
  </style>
</head>

<body>
  <div class="wrapper">
    <h4 class="chart-title">Adjusted net enrolment rate, primary, female (%) <span class="year"></span></h4>
    <div class="chart"></div>
    <p class="source">Data source: The World Bank</p>
  </div>
  <script src="//d3js.org/d3.v4.0.0-alpha.28.min.js"></script>
  <script>
    'use strict';

    const margin = {
      top: 20,
      right: 30,
      bottom: 40,
      left: 260
    };
    const width = 960 - margin.left - margin.right;
    const height = 400 - margin.top - margin.bottom;
    const percentFormat = d3.format('.0%');
    const leftPadding = 5;

    const delay = function (d, i) {
      return i * 40;
    };

    function sortData(data) {
      return data.sort((a, b) => b.value - a.value);
    }

    function removeGeoAreasWithNoData(data) {
      return data.filter(d => d.value);
    }

    function prepareData(data) {
      return data.reduce((accumulator, d) => {
        Object.keys(d).forEach((k) => {
          if (!Number.isInteger(+k)) {
            return;
          }
          let value;
          if (d[+k] === '..') {
            value = 0;
          } else {
            value = +d[+k] / 100;
          }
          const newEntry = {
            value,
            geoCode: d.CountryCode,
            geoName: d.Country,
          };
          if (accumulator[+k]) {
            accumulator[+k].push(newEntry);
          } else {
            accumulator[+k] = [newEntry];
          }
        });
        return accumulator;
      }, {});
    }

    function xAccessor(d) {
      return d.value;
    }

    function yAccessor(d) {
      return d.geoName;
    }

    const xScale = d3.scaleLinear()
      .range([0, width])
      .domain([0, 1]);

    const yScale = d3.scaleBand()
      .rangeRound([0, height], 0.1)
      .padding(0.1);

    function drawXAxis(el) {
      el.append('g')
        .attr('class', 'axis axis--x')
        .attr('transform', `translate(${leftPadding},${height})`)
        .call(d3.axisBottom(xScale).tickFormat(percentFormat));
    }

    function drawYAxis(el, data, t) {
      let axis = el.select('.axis--y');
      if (axis.empty()) {
        axis = el.append('g')
          .attr('class', 'axis axis--y');
      }

      axis.transition(t)
        .call(d3.axisLeft(yScale))
        .selectAll('g')
        .delay(delay);
    }

    function drawBars(el, data, t) {
      let barsG = el.select('.bars-g');
      if (barsG.empty()) {
        barsG = el.append('g')
          .attr('class', 'bars-g');
      }

      const bars = barsG
        .selectAll('.bar')
        .data(data, yAccessor);
      bars.exit()
        .remove();
      bars.enter()
        .append('rect')
        .attr('class', d => d.geoCode === 'WLD' ? 'bar wld' : 'bar')
        .attr('x', leftPadding)
        .merge(bars).transition(t)
        .attr('y', d => yScale(yAccessor(d)))
        .attr('width', d => xScale(xAccessor(d)))
        .attr('height', yScale.bandwidth())
        .delay(delay);
    }

    // 构造SVG对象
    const svg = d3.select('.chart').append('svg')
      .attr('width', width + margin.left + margin.right)
      .attr('height', height + margin.top + margin.bottom)
      .append('g')
      .attr('transform', `translate(${margin.left},${margin.top})`);
    // 全程车，区间车
    // 获取数据源
    fetch('./../static/csv/data.csv')
      .then((res) => res.text())
      .then((res) => {
        const respData = d3.csvParse(res);
        // console.log(respData);
        const data = prepareData(respData); // 获取处理后的数据源对象
        // console.log(data);
        const years = Object.keys(data).map(d => +d); // 年份数组
        const lastYear = years[years.length - 1]; // 获取最后一年
        let startYear = years[0]; // 开始年份
        let selectedData = removeGeoAreasWithNoData(sortData(data[startYear])); // 根据年份，获取数据
        // console.log('selectedData',selectedData);
        let geoAreas = selectedData.map(yAccessor);
        // console.log('geoAreas',geoAreas);

        // 修改年份标题
        // d3.select('.year').text(startYear);

        yScale.domain(geoAreas);
        drawXAxis(svg, selectedData);
        drawYAxis(svg, selectedData);
        drawBars(svg, selectedData);

        const interval = d3.interval(() => {
          const t = d3.transition().duration(400);

          startYear += 1;
          selectedData = removeGeoAreasWithNoData(sortData(data[startYear]));

          d3.select('.year').text(startYear);

          yScale.domain(selectedData.map(yAccessor));
          drawXAxis(svg, selectedData);
          drawYAxis(svg, selectedData, t);
          drawBars(svg, selectedData, t);

          if (startYear === lastYear) {
            interval.stop();
          }
        }, 1000);
      });
  </script>
</body>

</html>